package com.mrogrape.gui.application;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Stack;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import com.mrogrape.util.StringUtils;

public abstract class ApplicationFrame extends JFrame {

	/** serialVersionUID */
	private static final long serialVersionUID = 1L;
	
	public ApplicationFrame(String stringBundle, URL application, URL icons, URL menu){
		this.stringBundle = stringBundle;
		this.menu = menu;
		
		onLoadPreferences();
		onInitializeComponents();
		onCreateMenu();
		onApplyPreferences();
	}
	
	/**
	 * 从字符串资源集中获取一个字符串。
	 * 
	 * @param key
	 * @return
	 */
	public String getString(String key){
		if(this.strings == null){
			throw new IllegalStateException("String bundle not found.");
		}
		
		return this.strings.getString(key);
	}
	
	protected void onLoadPreferences(){}
	
	protected void onInitializeComponents(){
		this.strings = ResourceBundle.getBundle(this.stringBundle);
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	protected void onCreateMenu(){
		if(this.menu == null){
			return;
		}
		
		this.menuItems = new HashMap<String, JMenuItem>();
		this.menus = new HashMap<String, JMenu>();
		this.menubar = new JMenuBar();
		this.setJMenuBar(this.menubar);
		
		try {
			InputStream is = this.menu.openStream();
			XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(is);
			
			Stack<JMenu> menuStack = new Stack<JMenu>();
			Map<String,String> parameters = new HashMap<String,String>();
			
			while(parser.hasNext()){
				
				int event = parser.next();
				
				// Element Start
				if(event == XMLStreamConstants.START_ELEMENT){
					String elementName = parser.getLocalName();
					// Parameter Node
					if("parameter".equals(elementName)){
						
						String key = parser.getAttributeValue(null, "key");
						String value = parser.getAttributeValue(null, "value");
						parameters.put("${" + key + "}", value);
					}
					// Menu Node
					else if("menu".equals(elementName)){
						String id= parser.getAttributeValue(null, "id");
						String label = getParameterizedAttributeValue(parser, "label", parameters);
						
						JMenu menu = new JMenu(label);
						this.menus.put(id, menu);
						
						if(menuStack.size() == 0){
							this.menubar.add(menu);
						}
						else{
							JMenu parentMenu = menuStack.peek();
							parentMenu.add(menu);
						}
						
						menuStack.push(menu);
					}
				}
				// Element End
				else if(event == XMLStreamConstants.END_ELEMENT){
					String elementName = parser.getLocalName();
					if("menu".equals(elementName)){
						menuStack.pop();
					}
				}
			}
			
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XMLStreamException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private String getParameterizedAttributeValue(XMLStreamReader parser, String localName, Map<String,String> parameters){
		
		return replaceParameter(parameters, parser.getAttributeValue(null, localName));
	}
	
	private String replaceParameter(Map<String,String> parameters, String value){
		
		if(StringUtils.isEmpty(value)||!value.contains("$")){
			return value;
		}
		
		String out = value;
		Iterator<String> keys = parameters.keySet().iterator();
		
		while(keys.hasNext()){
			String key = keys.next();
			out = out.replace(key, parameters.get(key));
		}
		
		return out;
	}
	
	protected void onApplyPreferences(){}
	
	protected void onSavePreferences(){}
	

	private String stringBundle;
	private URL menu;
	private JMenuBar menubar;
	private Map<String,JMenuItem> menuItems;
	private Map<String,JMenu> menus;
	private ResourceBundle strings;
}
